﻿//Copyright (C) <2013>  <jonathan cleeve norton> All Rights Reserved 
//Contact jon.norton@fin-plus.co.uk website <http://www.fin-plus.co.uk/>
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FinPlusCommon;
using log = Logger.Logger;
using u = FinPlusUtility.Utility;

namespace FinPlusComponents
{
    public class FinPlusUpdateCache:FinPlusComponent
    {
        public override string Id { get; set; }
        public override string[] States { get { return new string[] { }; } }
        public override string[] TestStates { get { return new string[] { "ModelTest", "IsValid" }; } }
        public override IFinPlusFunctions Model { get { return _model; } }
        public override string ModelTest { get { return _model.ToString(); } }
        public override bool IsValid { get; set; }

        private enum Params{ Resend };

        private IFinPlusComponent _sourceConn;
        private IFinPlusFunctions _model;

        private readonly IDictionary<string, string> _cacheNames;
        private readonly IDictionary<string, Dictionary<string, Dictionary<string, IFinPlusItem>>> _cacheItems;
        private bool _hasInitialised;

        //construct
        public FinPlusUpdateCache(string cacheNames)
        {
            _cacheNames = u.ToDictionary(cacheNames, true);
            _cacheItems = new Dictionary<string, Dictionary<string, Dictionary<string, IFinPlusItem>>>();
        }

        //common control interface
        public override void Dock(object component, string dock)
        {
            try
            {
                _sourceConn = (IFinPlusComponent)component;
            }
            catch (Exception e)
            {
                IsValid = log.Log(Logger.Level.Error, Id, Config, e.Message, e);
            }
        }

        public override void Initialise()
        {
            try
            {
                if (_hasInitialised) return;

                _model = _sourceConn.Model.Clone();
                _model.Get(Params.Resend.ToString(), string.Empty, Item_Resend);

                foreach (var cacheItem in _cacheNames)
                    _model.Get(cacheItem.Key, new Function(), Item_Updated);

                IsValid = _hasInitialised = true;
            }
            catch (Exception e)
            {
                IsValid = log.Log(Logger.Level.Error, Id, Config, e.Message, e);
            }
        }

        public override void CommandRouter(IFinPlusFunction func) { }

        public override void Dispose()
        {
            if (_sourceConn != null)
                _sourceConn.Dispose();
        }

        //events
        private void Item_Updated(object sender, PropertyChangedEventArgs a)
        {
            var item = (IFinPlusItem)sender;

            if (!_cacheNames.ContainsKey(item.Name)) return;

            var keys = item.Key(_cacheNames[item.Name]).Split('|');

            if (!_cacheItems.ContainsKey(keys[0]))  
                _cacheItems[keys[0]] = new Dictionary<string, Dictionary<string, IFinPlusItem>>();

            if (!_cacheItems[keys[0]].ContainsKey(keys[1])) 
                _cacheItems[keys[0]][keys[1]] = new Dictionary<string, IFinPlusItem>();

            _cacheItems[keys[0]][keys[1]][keys[2]] = item.Clone(item.Id);
        }

        private void Item_Resend(object sender, PropertyChangedEventArgs a)
        {
            var item = (IFinPlusItem)sender;

            if (_cacheItems.ContainsKey(item.Id.ToString()) && _cacheItems[item.Id.ToString()].ContainsKey(item.Value))
               foreach (var i in _cacheItems[item.Id.ToString()][item.Value].Values.ToArray())
                   _model[item.Id].Get(item.Value).Set(i.Value);
        }
    }
}
